#include <src/pcps.h>
#include <src/input.h>
#include <src/blas_lapack.h>
#include <src/arena.h>
#include <src/timing.h>
#include <src/random.h>

//--------------------------------------------------------------------------------
// main -- pcps.exe main function
//--------------------------------------------------------------------------------

int main(int argc, char * argv[]) {

  // initialize MPI
  MPI::Init(argc, argv);
  const MPI::Comm & comm = MPI::COMM_WORLD;
  const int nproc = comm.Get_size();
  const int myrank = comm.Get_rank();
  if (myrank == 0)
    std::cout << boost::format("MPI initialized with %6i processors             elapsed time = %17.6f sec")
                 % nproc
                 % pcps::get_overall_timer().elapsed_seconds()
              << std::endl
              << std::endl;

  // initialize timers and start overall timer
  pcps::initialize_timers();
  pcps::start_overall_timer(0);

  //// set MKL to use one thread
  //MKL_Set_Num_Threads(1);

  // initialize global mutexes
  pcps::init_mutexes();

  // parse the input file and store the user's options in userinp
  const pcps::Input userinp(argc, argv);
  if (myrank == 0)
    std::cout << boost::format("Input file processed %6s                        elapsed time = %17.6f sec")
                 % ' '
                 % pcps::get_overall_timer().elapsed_seconds()
              << std::endl
              << std::endl;

  // set the random seed
  pcps::set_seed(userinp.global_seed());

  // run the calculation using either real or complex numbers
  if (userinp.scalar_type() == pcps::keyword::Scalar_Real)
    pcps::driver<double>(userinp);
  else if (userinp.scalar_type() == pcps::keyword::Scalar_Complex)
    pcps::driver< std::complex<double> >(userinp);
  else
    throw pcps::Exception( (boost::format("unknown scalar type \"%s\"") % userinp.scalar_type()).str() );

  // destroy global mutexes
  pcps::destroy_mutexes();

  // finalize timers
  pcps::finalize_timers();

  // print elapsed time on root node
  if (myrank == 0)
    std::cout << boost::format("pcps program finished                              elapsed time = %17.6f sec")
                 % pcps::get_overall_timer().elapsed_seconds()
              << std::endl;

  // finalize MPI
  MPI::Finalize();

  return 0;

}
